from datetime import datetime, timedelta
from fastapi.responses import JSONResponse
from fastapi import APIRouter, Query, Request
from tortoise import fields
from tortoise.expressions import Q, F

from app.controllers.goods.sku import sku_controller
from app.controllers.orders.list import orders_list_controller
from app.models import AppointmentList, AppointmentLock, AppointmentProject, AppointmentInstrument, CustomerUser, \
    AppointmentSalon, AppointmentCategory, GoodsSku, AppointmentDesigner
from app.schemas.appointment import AppointmentLockCreate, AppointmentListCreate, AppointmentGetPrice
from app.schemas.orders import OrdersListCreateMini
from app.settings import settings
from app.schemas.base import Success, SuccessExtra, Fail
from app.controllers.appointment.designer import appointment_designer_controller
from app.controllers.appointment.space import appointment_space_controller
from app.controllers.appointment.project import appointment_project_controller
from app.controllers.appointment.mini import appointment_mini_controller
from app.controllers.appointment.lock import appointment_lock_controller
from app.controllers.appointment.list import appointment_list_controller
from app.controllers.appointment.salon import appointment_salon_controller
from app.core.redis_base import redis_get, redis_set
from app.core.dependency import DependCustomerAuth
from app.core.ctx import CTX_USER_ID

mini_appointment_router = APIRouter()


@mini_appointment_router.get("/get_salons", summary="获取沙龙列表")
async def do_get_salons():
    now = datetime.now()
    q = Q(status=True)
    total, data = await appointment_salon_controller.do_list(page=1, page_size=100, search=q)
    for item in data:
        date = datetime.strptime(item["date"], "%Y-%m-%d %H:%M:%S")
        item['city_name'] = settings.APPOINTMENT_CITY[item['city_id']]
        if date <= now:
            item["expire"] = 1
        else:
            item["expire"] = 0
    return SuccessExtra(data=data, total=len(data), page=1, page_size=100)


@mini_appointment_router.get("/list", summary=f"我的预约列表", dependencies=[DependCustomerAuth])
async def do_list(
        page: int = Query(1, description="页码"),
        page_size: int = Query(10, description="每页数量"),
        type: int = Query(None, description="大类"),
        d_type: int = Query(None, description="小类"),
        status: int = Query(None, description="状态"),
        space_id: int = Query(None, description="门店id"),
        start_time: str = Query("", description="开始时间"),
        end_time: str = Query("", description="结束时间"),
        customer_id=Query(0, description="用户id"),

):
    user_id = CTX_USER_ID.get()
    q = Q()
    if customer_id:
        user_id = customer_id
    q &= Q(user_id=user_id)
    if status in {0, 1, 2, 3}:
        q &= Q(status=status)
    if type:
        q &= Q(type=type)
    if d_type:
        q &= Q(type=d_type)
    if space_id:
        q &= Q(type=space_id)
    if start_time and end_time:
        q &= Q(time__range=[start_time, end_time])
    elif start_time:
        q &= Q(time__gte=start_time)
    elif end_time:
        q &= Q(time__lte=end_time)
    total, data = await appointment_list_controller.do_list(page=page, page_size=page_size, search=q)
    space_objs = await appointment_space_controller.level_list()

    for item in data:
        item['type_name'] = settings.APPOINTMENT_T[item['type']]
        if item['d_type'] > 0:
            item['d_type_name'] = settings.APPOINTMENT_TYPE[item['d_type']]
        else:
            item['d_type_name'] = "无"
        if item['space_id'] > 0:
            item['space_name'] = space_objs[item['space_id']]
        else:
            item['space_name'] = "无"
        item['status_name'] = settings.APPOINTMENT_STATUS[item['status']]
        if item['designer_names']:
            item['designer_name_s'] = ", ".join(item['designer_names'])
        else:
            item['designer_name_s'] = ""
        if item['ex_project_names']:
            item['ex_names'] = ", ".join(item['ex_project_names'])
            item['project_name_s'] = f"{item['project_name']}({item['ex_names']})"
        else:
            item['ex_names'] = ""
    return SuccessExtra(data=data, total=total, page=page, page_size=page_size)


@mini_appointment_router.get("/get_salon", summary="获取沙龙详情")
async def do_get_salon(
        data_id: int = Query(0, description="沙龙id"),
):
    data = await appointment_salon_controller.do_detail(data_id=data_id)
    return Success(data=data)


@mini_appointment_router.get("/get_type", summary="获取预约类型")
async def do_get_type():
    level_objs = settings.APPOINTMENT_TYPE
    data = []
    key = 0
    for level in level_objs:
        if level:
            data.append({"id": key, "name": level})
        key += 1
    return Success(data=data)


@mini_appointment_router.get("/get_space", summary="获取门店列表")
async def do_get_space(
        request: Request,
        name: str = Query(None, description="门店名称"),
):
    q = Q()
    if name:
        q &= Q(name__contains=name)
    # data = await redis_get("appointment:space", request.state.redis)
    # if data is None:
    total, data = await appointment_space_controller.do_list(page=1, page_size=100, search=q)
    # await redis_set("appointment:space", data, request.state.redis)
    return SuccessExtra(data=data, total=len(data), page=1, page_size=100)


@mini_appointment_router.get("/get_projects", summary="获取项目列表")
async def do_get_projects(
        request: Request,
        category_id: int = Query(0, description="项目分类:1预约项目2搭配项目"),
        space_id: int = Query(1, description="门店id"),
        name: str = Query(None, description="商品名称"),
):
    data = await redis_get(f"projects:projects{space_id}_{category_id}", request.state.redis)
    if data is None:
        # 判断门店的项目ids
        space = await appointment_space_controller.do_detail(space_id)
        space_project_roles = space['project_roles']
        ##获取预约项目大类
        q1 = Q()
        if category_id > 0:
            q1 &= Q(parent_id=category_id)

        q2 = Q()
        if space_project_roles:
            q2 &= Q(id__in=space_project_roles)
        data = await AppointmentCategory.filter(q1).all().values("id", "name", "desc")
        for item in data:
            q3 = q2 & Q(type=item['id'])
            if name:
                q3 &= Q(name__contains=name)
            total, project_data = await appointment_project_controller.do_list(page=1, page_size=100, search=q3)
            item["projects"] = project_data
        ##await redis_set(f"projects:projects{space_id}_{type_id}_{d_type_id}_{doctor_id}", data, request.state.redis)
    return SuccessExtra(data=data)


@mini_appointment_router.get("/get_designers", summary="获取该门店下的医生列表")
async def do_get_designers(
        request: Request,
        type_id: int = Query(0, description="预约大类"),
        d_type_id: int = Query(0, description="预约小类"),
        space_id: int = Query(1, description="门店id"),
        designer_type: int = Query(1, description="对象类型1助理2面诊师3医生"),
        project_id: int = Query(0, description="项目id"),
):
    q = Q(status=True)
    if designer_type:
        q &= Q(type=designer_type)
    if space_id:
        q &= Q(space_id__contains=[space_id])
    if d_type_id:
        q &= Q(doctor_type__contains=[d_type_id])
    if project_id > 0:
        q &= Q(project_roles__contains=[project_id])

    data = await redis_get(f"designers:designers{space_id}_{type_id}_{d_type_id}_{designer_type}", request.state.redis)
    print("缓存", data)
    if data is None:
        total, data = await appointment_designer_controller.do_list(page=1, page_size=100, search=q)
        ##await redis_set(f"designers:designers{space_id}_{type_id}_{d_type_id}_{designer_type}", data, request.state.redis)
    return SuccessExtra(data=data, total=len(data), page=1, page_size=100)


@mini_appointment_router.get("/get_dates", summary="获取该可选的日期列表")
async def do_get_dates(
        request: Request,
        type_id: int = Query(1, description="预约大类"),
        d_type_id: int = Query(1, description="预约小类"),
        space_id: int = Query(0, description="门店id"),
        doctor_id: list = Query(None, description="医生id#这里改成多选了"),
        project_id: int = Query(0, description="项目id"),
):
    dates_all = await appointment_mini_controller.get_date(request, space_id, d_type_id, doctor_id, project_id)
    return SuccessExtra(data=dates_all)


@mini_appointment_router.get("/get_times", summary="获取该可选的时间列表")
async def do_get_times(
        request: Request,
        type_id: int = Query(1, description="预约大类"),
        d_type_id: int = Query(1, description="预约小类"),
        space_id: int = Query(0, description="门店id"),
        doctor_ids: str = Query("", description="医生id:2,3"),
        project_id: int = Query(0, description="项目id"),
        date: str = Query("", description="日期[02.24]"),
):
    await appointment_lock_controller.do_delete_5min(request)
    if doctor_ids:
        doctor_ids = doctor_ids.split(",")
    full_date_str = convert_to_yyyy_mm_dd(date)
    times_all = await appointment_mini_controller.get_times(request, space_id, d_type_id, doctor_ids, project_id,
                                                            full_date_str)
    return SuccessExtra(data=times_all)


def convert_to_yyyy_mm_dd(date_str, year=None):
    # 分割字符串，获取月份和日期
    month, day = date_str.split('.')
    # 如果未指定年份，则使用当前年份
    if year is None:
        year = datetime.now().year
    # 构建完整的日期字符串
    full_date_str = f"{year}-{month}-{day}"
    # 验证日期是否有效（可选）
    try:
        datetime.strptime(full_date_str, '%Y-%m-%d')
    except ValueError:
        return Fail(msg="日期格式错误")

    return full_date_str


@mini_appointment_router.post("/price", summary="获取时长和金额", dependencies=[DependCustomerAuth])
async def do_price(
        request: Request,
        data_in: AppointmentGetPrice,
):
    user_id = CTX_USER_ID.get()
    project_id = data_in.project_id
    projects_all = []
    if data_in.ex_project_ids:
        ex_project_ids = data_in.ex_project_ids.copy()  ##[2,3]
        projects_all = ex_project_ids
    projects_all.append(project_id)  ##1,2,3
    ex_data = await AppointmentProject.filter(id__in=projects_all).values("id", "sku_id", "interval")
    longs = 0
    price = 0
    for item in ex_data:
        longs += item["interval"]
        if item["sku_id"] > 0:
            sku_price = await sku_controller.get_price_by_user(sku_id=item["sku_id"], user_id=user_id)
        else:
            sku_price = 0
        price += sku_price
    price = price * data_in.come_nums
    data = {
        "longs": longs,
        "price": price
    }
    return SuccessExtra(data=data)


@mini_appointment_router.post("/slot_lock", summary="点击时间，锁定时间段", dependencies=[DependCustomerAuth])
async def do_slot_lock(
        request: Request,
        data_in: AppointmentLockCreate,
):
    user_id = CTX_USER_ID.get()
    data_in.user_id = user_id
    ##删除5分钟之前的数据和自己之前抢到的格位
    await AppointmentLock.filter(user_id=user_id).delete()
    await appointment_lock_controller.do_delete_5min(request)
    # ##计算lock当前相同时间段的条数
    q = Q()
    # 将或逻辑部分用括号包起来
    or_condition = Q()
    for designer_id in data_in.designer_ids:
        or_condition |= Q(designer_ids__contains=[designer_id])
    q = or_condition & Q(time=data_in.time)

    query = AppointmentLock.filter(q)
    count = await query.count()
    lock = await query.first()
    if count >= 1 and lock.user_id != user_id:
        return JSONResponse(content={"code": 400, "msg": "此时间段被别人抢先了"}, status_code=200)
    await appointment_lock_controller.do_create(request, obj_in=data_in)
    return Success()


# @mini_appointment_router.post("/create", summary="提交预约表单", dependencies=[DependCustomerAuth])
# async def do_save(
#         request: Request,
#         data_in: AppointmentListCreate,
# ):
#     user_id = CTX_USER_ID.get()
#     if data_in.user_id:
#         user_id = data_in.user_id
#     appointment = await AppointmentList.filter(user_id=user_id).filter(time=data_in.time).first()
#     if appointment:
#         return JSONResponse(content={"code": 400, "msg": "已经预约成功啦"}, status_code=200)
#
#     ##保存提交表单
#     user = await CustomerUser.filter(id=user_id).first().values("name", "card_no", "role_id", "phone")
#     data_in.user_id = user_id
#     data_in.user_name = user['name']
#     data_in.user_card_no = user['card_no']
#     data_in.user_type = user['role_id']
#     data_in.user_phone = user['phone']
#     data_in.status = 1
#     app_sku = []
#     projects_all = []
#
#     if data_in.project_id == 0:
#         data_in.project_id = data_in.ex_project_ids[0]  ##1
#         del data_in.ex_project_ids[0]
#     if data_in.ex_project_ids:
#         ex_project_ids = data_in.ex_project_ids.copy()  ##[2,3]
#         projects_all = ex_project_ids
#         projects_all.append(data_in.project_id)  ##1,2,3
#     if data_in.designer_ids:
#         designer_data = await AppointmentDesigner.filter(id__in=data_in.designer_ids).values("name")
#         data_in.designer_names = [item["name"] for item in designer_data]
#     if data_in.ex_project_ids:
#         ex_data = await AppointmentProject.filter(id__in=data_in.ex_project_ids).values("name")
#         data_in.ex_project_names = [item["name"] for item in ex_data]
#     project = await AppointmentProject.filter(id=data_in.project_id).first().values("name")
#     data_in.project_name = project["name"]
#     goods = await AppointmentProject.filter(id__in=projects_all).all().values("sku_id")
#     num = data_in.come_nums
#
#     if goods:
#         for item in goods:
#             app_sku.append({"sku_id": item['sku_id'], "num": num})
#     order_in = OrdersListCreateMini(
#         type=1,
#         sku=app_sku,
#         address_id=data_in.space_id
#     )
#     if data_in.designer_ids:
#         designer_data = await AppointmentDesigner.filter(id__in=data_in.designer_ids).values("name")
#         data_in.designer_names = [item["name"] for item in designer_data]
#     if data_in.ex_project_ids:
#         ex_data = await AppointmentProject.filter(id__in=data_in.ex_project_ids).values("name")
#         data_in.ex_project_names = [item["name"] for item in ex_data]
#     project = await AppointmentProject.filter(id=data_in.project_id).first().values("name")
#     data_in.project_name = project["name"]
#     ret = await orders_list_controller.do_create(obj_in=order_in, user_id=user_id)
#     if ret["pay_status"] == 1:
#         data_in.order_id = ret["order_id"]
#         ##待支付状态，预约状态为0，支付成功后需要设置为1
#         data_in.status = 0
#         await appointment_list_controller.do_create(obj_in=data_in)
#         # ##删除lock表user_id是这个人的
#         # await appointment_lock_controller.do_delete_user(request,user_id)
#         ret = {
#             "order_id": data_in.order_id
#         }
#         return Success(msg="下单成功", data=ret)
#     else:
#         return Fail(msg=ret["msg"])


@mini_appointment_router.post("/create", summary="提交预约表单", dependencies=[DependCustomerAuth])
async def do_save(
        request: Request,
        data_in: AppointmentListCreate,
):
    user_id = CTX_USER_ID.get()
    if data_in.user_id:
        user_id = data_in.user_id
    appointment = await AppointmentList.filter(user_id=user_id).filter(time=data_in.time).first()
    if appointment:
        return JSONResponse(content={"code": 400, "msg": "已经预约成功啦"}, status_code=200)
    if data_in.type == 3:
        salon = await AppointmentSalon.filter(id=data_in.project_id).first().values("number", "number_have")
        number = salon['number']
        number_have = salon['number_have']
        if number_have >= number:
            return JSONResponse(content={"code": 400, "msg": "报名人数已满"}, status_code=200)

    ##保存提交表单
    user = await CustomerUser.filter(id=user_id).first().values("name", "card_no", "role_id", "phone")
    data_in.user_id = user_id
    data_in.user_name = user['name']
    data_in.user_card_no = user['card_no']
    data_in.user_type = user['role_id']
    data_in.user_phone = user['phone']

    if data_in.type == 1:
        ##先生成订单然后付款成功后提交预约{sku_id:1,num:2}
        app_sku = []
        projects_all = []
        project_id = data_in.project_id  ##1
        if data_in.ex_project_ids:
            ex_project_ids = data_in.ex_project_ids.copy()  ##[2,3]
            projects_all = ex_project_ids
        projects_all.append(project_id)  ##1,2,3
        goods = await AppointmentProject.filter(id__in=projects_all).all().values("sku_id")
        num = data_in.come_nums
        if goods:
            for item in goods:
                app_sku.append({"sku_id": item['sku_id'], "num": num})
        order_in = OrdersListCreateMini(
            type=1,
            sku=app_sku,
            address_id=data_in.space_id,
            status=data_in.status
        )
        if data_in.designer_ids:
            designer_data = await AppointmentDesigner.filter(id__in=data_in.designer_ids).values("name")
            data_in.designer_names = [item["name"] for item in designer_data]
        if data_in.ex_project_ids:
            ex_data = await AppointmentProject.filter(id__in=data_in.ex_project_ids).values("name")
            data_in.ex_project_names = [item["name"] for item in ex_data]
        project = await AppointmentProject.filter(id=project_id).first().values("name")
        data_in.project_name = project["name"]
        ret = await orders_list_controller.do_create(obj_in=order_in, user_id=user_id)
        if ret["pay_status"] == 1:
            data_in.order_id = ret["order_id"]
            ##待支付状态，预约状态为0，支付成功后需要设置为1
            data_in.status = data_in.status
            await appointment_list_controller.do_create(obj_in=data_in)
            # ##删除lock表user_id是这个人的
            # await appointment_lock_controller.do_delete_user(request,user_id)
            return Success(msg="下单成功", data=ret)
        else:
            return Fail(msg=ret["msg"])

    if data_in.type == 3:
        await appointment_list_controller.do_create(obj_in=data_in)
        await AppointmentSalon.filter(id=data_in.project_id).update(number_have=F('number_have') + 1)

    ret = {
        "order_id": data_in.order_id
    }
    return SuccessExtra(msg="提交成功", data=ret)

async def get_price(data_in: AppointmentGetPrice, user_id: int):
    project_id = data_in.project_id
    if project_id > 0:
        projects_all = []
        if data_in.ex_project_ids:
            ex_project_ids = data_in.ex_project_ids.copy()  ##[2,3]
            projects_all = ex_project_ids
        projects_all.append(project_id)  ##1,2,3
        ex_data = await AppointmentProject.filter(id__in=projects_all).values("id", "sku_id", "interval")
        longs = 0
        price = 0
        for item in ex_data:
            longs += item["interval"]
            if item["sku_id"] > 0:
                sku_price = await sku_controller.get_price_by_user(sku_id=item["sku_id"], user_id=user_id)
            else:
                sku_price = 0
            price += sku_price

        price = price * data_in.come_nums
        data = {
            "longs": longs,
            "price": price
        }
    else:
        data = {
            "longs": 30,
            "price": 0
        }
    return data